package com.stone.design.mode.observer;

import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 观察者事件总线（观察者同步执行）
 * guava也提供了观察者模式的事件总线，支持非常强大的功能，可参考：https://blog.csdn.net/wangdong5678999/article/details/80561198
 *
 * @author Mr_wenpan@163.com 2021/11/30 2:20 下午
 */
public class EventBus<T> {

    /**
     * 事件总线标识符
     */
    protected final String identifier;

    /**
     * 事件总线上的所有观察者
     */
    protected final List<? extends Observer<T>> observers;

    /**
     * 构造事件总线
     *
     * @param identifier 事件总线标识
     * @param observers  观察者列表
     */
    public EventBus(String identifier, List<? extends Observer<T>> observers) {
        // 初始化观察者集合，按照order排序
        this.identifier = identifier;
        this.observers = Optional.ofNullable(observers).orElse(new ArrayList<>())
                .stream().sorted(Comparator.comparingInt(Observer::order)).collect(Collectors.toList());
    }

    /**
     * 不带任何参数的唤醒所有观察者
     *
     * @param target 变化主体
     * @author Mr_wenpan@163.com 2021/11/30 3:22 下午
     */
    public void notifyObservers(T target) {
        notifyObservers(target, new Object[]{});
    }

    /**
     * 唤醒所有观察者
     *
     * @param target 变化主体
     * @param args   参数
     * @author Mr_wenpan@163.com 2021/11/30 3:10 下午
     */
    public void notifyObservers(T target, Object... args) {
        if (CollectionUtils.isEmpty(observers)) {
            return;
        }

        for (Observer<T> observer : observers) {
            observer.onListener(target, args);
        }
    }

    public String getIdentifier() {
        return identifier;
    }
}